#pragma once

#include <iostream>
#include <cstdio>
#include <string>
#include <cerrno>
// mkfifo
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
const std::string comm_path = "./myfifo";

#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define BaseSize 4096

class NamePiped
{

private:

    //打开文件的方法不想被看到，给外界提供调用，告诉外界的服务端（）和客户端是否打开成功
    bool OpenNamedPipe(int mode)
    {
        _fd = open(_fifo_path.c_str(), mode);
        if (_fd < 0)
            return false;
        return true;
    }

public:
    NamePiped(const std::string path, int who)
        : _fifo_path(path), _id(who), _fd(DefaultFd)
    {
        // 是创建者才需要创建管道，使用者只需要初始化管道就可以
        if (_id == Creater)
        {
            int res = mkfifo(path.c_str(), 0666);
            if (res != 0)
            {
                perror("mkfifo");
            }
            std::cout << "creater create named pipe" << std::endl;
        }
    }

    bool OpenForRead()
    {
        return OpenNamedPipe(Read); 
    }

    bool OpenForWrite()
    {
        return OpenNamedPipe(Write);
    }

    // const &: const std::string &XXX   纯输入
    // *      : std::string *            纯输出
    // &      : std::string &            输入输出

    //读取管道
    int ReadNamedPipe(std::string *out)
    {
        char buffer[BaseSize];
        //将_fd文件的内容读取到buffer
        int n = read(_fd, buffer, sizeof(buffer));
        if(n > 0)
        {
            buffer[n] = 0;
            *out = buffer;
        }
        return n;
    }
    //写入管道
    int WriteNamedPipe(const std::string &in)
    {
        // 向_fd文件写入内容，写in, 写入in的大小
        return write(_fd, in.c_str(), in.size());
    }

    ~NamePiped()
    {
        // 是创建者才可以删除管道，使用者不用管
        if (_id == Creater)
        {
            int res = unlink(_fifo_path.c_str());
            if (res != 0)
            {
                perror("unlink");
            }
            std::cout << "creater free named pipe" << std::endl;
        }
        //析构时关闭各自的文件描述符
        if(_fd != DefaultFd) close(_fd);
    }

private:
    const std::string _fifo_path;
    int _id;
    int _fd;
};
